﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.Threading;

namespace ILMergeUI
{
    public partial class Form1 : Form
    {
        #region Attributes

        int SizeFullWidth = 785;
        int SizeFullHeight = 405;
        int SizeSimpleWidth = 380;
        int SizeSimpleHeight = 405;
        int ViewLogStatus = 0;

        int DefaultPlatIndex = 1;
        int SelectedPlatIndex = 1;

        string FilePath = Application.StartupPath + @"\Setting.ini";
        QT.IO.INIFile IniFile;
        private Thread Thread;
        private delegate void outTxt(string txt);
        private delegate void setButton(bool isenable);

        #endregion

        #region Form

        public Form1()
        {
            InitializeComponent();
            ReleaseFile();
            IniFile = new QT.IO.INIFile(FilePath);
            InitPlatForm();
            InitForm();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            SaveSetting();
            e.Cancel = false;
        }

        #endregion

        #region Button

        //打开主程序文件
        private void btnOpenFile_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.ValidateNames = true;
            this.openFileDialog1.Multiselect = false;
            this.openFileDialog1.Filter = "应用程序|*.exe";
            this.openFileDialog1.FilterIndex = 1;
            this.openFileDialog1.FileName = "";
            if (this.openFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }
            this.tbOpenFile.Text = this.openFileDialog1.FileName;
        }

        //打开程序集
        private void btnOpenDll_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.ValidateNames = true;
            this.openFileDialog1.Multiselect = true;
            this.openFileDialog1.Filter = "动态链接库|*.dll|应用程序|*.exe|所有文件|*.*";
            this.openFileDialog1.FilterIndex = 1;
            this.openFileDialog1.FileName = "";
            if (this.openFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }
            foreach (string File in this.openFileDialog1.FileNames)
            {
                this.lbDll.Items.Add(File);
            }
        }

        //移除程序集
        private void btnRemoveDll_Click(object sender, EventArgs e)
        {
            if (this.lbDll.SelectedItems != null)
            {
                while (this.lbDll.SelectedItems.Count > 0)
                {
                    this.lbDll.Items.Remove(this.lbDll.SelectedItems[0]);
                }
            }
        }

        //设置目标文件路径
        private void btnSaveFile_Click(object sender, EventArgs e)
        {
            this.saveFileDialog1.ValidateNames = true;
            this.saveFileDialog1.Filter = "动态链接库|*.dll|应用程序|*.exe";
            if (this.tbOpenFile.Text.Length == 0)
            {
                this.saveFileDialog1.FilterIndex = 1;
                this.saveFileDialog1.DefaultExt = "dll";
                this.saveFileDialog1.FileName = "NewDll";
            }
            else
            {
                this.saveFileDialog1.FilterIndex = 2;
                this.saveFileDialog1.DefaultExt = "exe";
                this.saveFileDialog1.FileName = "NewApp";
            }
            this.saveFileDialog1.AddExtension = true;
            if (this.saveFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }
            this.tbSaveFile.Text = this.saveFileDialog1.FileName;
        }

        //执行操作
        private void btnOK_Click(object sender, EventArgs e)
        {
            if (!CheckInput()) return;
            this.SelectedPlatIndex = this.cbbPlatform.SelectedIndex;

            Thread = new Thread(new ThreadStart(ExportFile));
            Thread.Start();
        }

        //查看日志
        private void btnViewLog_Click(object sender, EventArgs e)
        {
            if (ViewLogStatus == 0)
            {
                this.Size = new Size(SizeFullWidth, SizeFullHeight);
                this.btnViewLog.Text = "隐藏日志";
                ViewLogStatus = 1;
            }
            else
            {
                this.Size = new Size(SizeSimpleWidth, SizeSimpleHeight);
                this.btnViewLog.Text = "查看日志";
                ViewLogStatus = 0;
            }
        }

        #endregion

        #region Method

        //初始化程序
        private void InitForm()
        {
            string MainExe="";
            string Dll="";
            string PlatID = "";
            int PlatIndex=0;
            string SavePath="";
            if (IniFile.ReadInivalue("Setting", "MainExe", out MainExe))
            {
                this.tbOpenFile.Text = MainExe;
            }
            if (IniFile.ReadInivalue("Setting", "Dlls", out Dll))
            {
                string[] Dlls = Dll.Split(';');
                this.lbDll.Items.Clear();
                for (int i = 0; i < Dlls.Length; i++)
                {
                    if(!string.IsNullOrEmpty(Dlls[i])) this.lbDll.Items.Add(Dlls[i]);
                }
            }
            if (IniFile.ReadInivalue("Setting", "PlatIndex", out PlatID))
            {
                this.cbbPlatform.SelectedIndex = int.TryParse(PlatID, out PlatIndex) ? PlatIndex : DefaultPlatIndex;
            }
            if (IniFile.ReadInivalue("Setting", "SavePath", out SavePath))
            {
                this.tbSaveFile.Text = SavePath;
            }
        }

        //初始化.Net平台列表
        private void InitPlatForm()
        {
            this.cbbPlatform.Items.Add(".Net V1.1");
            this.cbbPlatform.Items.Add(".Net V2.0");
            this.cbbPlatform.Items.Add(".Net V3.0");
            this.cbbPlatform.Items.Add(".Net V3.5");
            this.cbbPlatform.Items.Add(".Net V4.0");
            this.cbbPlatform.Items.Add(".Net V4.5");
            this.cbbPlatform.SelectedIndex = DefaultPlatIndex;
        }

        //验证输入
        private bool CheckInput()
        {
            if (this.tbOpenFile.Text.Length > 0 && (!this.tbOpenFile.Text.ToLower().EndsWith(".exe")))
            {
                MessageBox.Show("主程序必须是EXE文件");
                return false;
            }
            if (this.lbDll.Items.Count == 0)
            {
                MessageBox.Show("请添加程序集");
                return false;
            }
            if (this.tbSaveFile.Text.Length == 0)
            {
                MessageBox.Show("请选择输出文件路径");
                return false;
            }
            if (this.tbOpenFile.Text.Length == 0 && this.tbSaveFile.Text.ToLower().EndsWith(".exe") && (!this.lbDll.Items[0].ToString().ToLower().EndsWith(".exe")))
            {
                MessageBox.Show("您没有选择主程序，且第一个程序集不为exe程序，不能导出为exe程序");
                return false;
            }
            return true;
        }

        //程序合成
        private void ExportFile()
        {
            this.btnOK.Invoke(new setButton(SetButton), new object[] { false });

            string FileType;
            string PlatType;
            string Parameter;

            #region 判断输出文件类型

            if (this.tbSaveFile.Text.ToLower().EndsWith(".exe"))
            {
                FileType = "winexe";
            }
            else
            {
                FileType = "dll";
            }

            #endregion

            #region 判断.Net平台版本

            switch (SelectedPlatIndex)
            {
                case 0:
                    PlatType = "v1.1";
                    break;
                case 1:
                    PlatType = "v2";
                    break;
                case 2:
                    PlatType = "v3";
                    break;
                case 3:
                    PlatType = "v3.5";
                    break;
                case 4:
                    PlatType = "v4";
                    break;
                case 5:
                    PlatType = "v4.5";
                    break;
                default:
                    PlatType = "v2";
                    break;
            }

            #endregion

            #region 组合参数

            Parameter = "/ndebug /log /target:" + FileType + " /targetplatform:" + PlatType + " /out:" + this.tbSaveFile.Text + " " + this.tbOpenFile.Text;
            for (int i = 0; i < this.lbDll.Items.Count; i++)
            {
                Parameter += " " + this.lbDll.Items[i].ToString();
            }

            #endregion

            ReleaseFile();

            #region 执行ILMerge

            Process process = new Process();
            process.StartInfo.RedirectStandardInput = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.CreateNoWindow = true;
            process.StartInfo.WorkingDirectory = Application.StartupPath;
            process.StartInfo.FileName = "ILMerge.exe";
            process.StartInfo.Arguments = Parameter;
            process.StartInfo.UseShellExecute = false;
            process.Start();
            string Result = process.StandardOutput.ReadToEnd();
            this.rtbLog.Invoke(new outTxt(OutTxt), new object[] { Result });
            process.WaitForExit();
            process.Close();

            #endregion

            Regex regex = new Regex("ILMerge: Done.");

            if (regex.IsMatch(Result))
            {
                MessageBox.Show("操作成功");
            }
            else
            {
                MessageBox.Show("操作失败", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
            this.btnOK.Invoke(new setButton(SetButton), new object[] { true });
        }

        private void SetButton(bool isenable)
        {
            this.btnOK.Enabled = isenable;
        }

        private void OutTxt(string txt)
        {
            this.rtbLog.Clear();
            this.rtbLog.AppendText(txt);
        }

        //保存操作配置
        private void SaveSetting()
        {
            IniFile.WriteInivalue("Setting", "MainExe", this.tbOpenFile.Text);
            string Dlls="";
            if (this.lbDll.Items.Count > 0)
            {
                for (int i = 0; i < this.lbDll.Items.Count; i++)
                {
                    Dlls += this.lbDll.Items[i].ToString() + ";";
                }
                Dlls = Dlls.Remove(Dlls.Length - 1);
            }
            IniFile.WriteInivalue("Setting", "Dlls", Dlls);
            IniFile.WriteInivalue("Setting", "PlatIndex", this.cbbPlatform.SelectedIndex.ToString());
            IniFile.WriteInivalue("Setting", "SavePath", this.tbSaveFile.Text);
        }

        #endregion

        #region ReleaseFile

        private void ReleaseFile()
        {
            string ILMergeFile=@".\ILMerge.exe";
            if (!File.Exists(ILMergeFile))
            {
                byte[] buffer = Properties.Resources.ILMerge;//这个是添加EXE到程序资源时的名称
                FileStream FS = new FileStream(ILMergeFile, FileMode.Create);//新建文件
                BinaryWriter BWriter = new BinaryWriter(FS);//以二进制打开文件流
                BWriter.Write(buffer, 0, buffer.Length);//从资源文件读取文件内容，写入到一个文件中
                BWriter.Close();
                FS.Close();
            }
            string SettingFile = @".\Setting.ini";
            if (!File.Exists(SettingFile))
            {
                byte[] buffer = System.Text.Encoding.Default.GetBytes(Properties.Resources.Setting);//这个是添加EXE到程序资源时的名称
                FileStream FS = new FileStream(SettingFile, FileMode.Create);//新建文件
                BinaryWriter BWriter = new BinaryWriter(FS);//以二进制打开文件流
                BWriter.Write(buffer, 0, buffer.Length);//从资源文件读取文件内容，写入到一个文件中
                BWriter.Close();
                FS.Close();
            }
        }

        #endregion
    }
}
